package com.kidback.bbloc259.network.base;

import android.util.Log;

import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import okhttp3.Dispatcher;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Converter;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by meikai on 2020/05/16.
 */
public abstract class NetWorkApi {

    static List<ResponseHandler> iErrorHandlerList = new ArrayList<>();
    private static HashMap<String, Retrofit> retrofitHashMap = new HashMap<>();

    protected INetWorkConfig iNetWorkRequiredInfo;


    protected abstract String getBaseUrl();

    protected abstract Interceptor getInterceptor();

    protected Converter.Factory getConverterFactory(){
        return GsonConverterFactory.create(createGson());
    }

    public void initInner(INetWorkConfig netWorkRequiredInfo) {
        iNetWorkRequiredInfo = netWorkRequiredInfo;
    }

    public <T> T getService(Class<T> service) {
        return getRetrofit(service).create(service);
    }

    public Retrofit getRetrofit(Class service) {
        Retrofit retrofit = retrofitHashMap.get(service.getName());
        if (retrofit != null) {
            return retrofit;
        }

        Retrofit.Builder retrofitBuilder = new Retrofit.Builder();
        retrofitBuilder.baseUrl(getBaseUrl());
        retrofitBuilder.client(getOkHttpClient());
        retrofitBuilder.addConverterFactory(getConverterFactory());
        retrofitBuilder.addCallAdapterFactory(RxJava2CallAdapterFactory.create());

        retrofit = retrofitBuilder.build();
        retrofitHashMap.put(service.getName(), retrofit);
        return retrofit;
    }

    protected ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(10, 100,
                24L, TimeUnit.HOURS, new SynchronousQueue<Runnable>(), new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                Thread thread = new Thread(r);
                thread.setName("self retrofit thread");
                return thread;
            }
        });
    }

    private OkHttpClient getOkHttpClient() {
        OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();

        Dispatcher dispatcher = new Dispatcher(newCachedThreadPool());
        okHttpClientBuilder.dispatcher(dispatcher);

        okHttpClientBuilder.callTimeout(30_000, TimeUnit.MILLISECONDS);
        okHttpClientBuilder.connectTimeout(10_000, TimeUnit.MILLISECONDS);
        okHttpClientBuilder.writeTimeout(10_000, TimeUnit.MILLISECONDS);
        okHttpClientBuilder.readTimeout(10_000, TimeUnit.MILLISECONDS);

        Interceptor interceptor = getInterceptor();
        if (interceptor != null) {
            okHttpClientBuilder.addInterceptor(interceptor);
        }

        //官方请求日志
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
            @Override
            public void log(@NotNull String s) {

                if (s.startsWith("-->")) {
                    if (s.startsWith("--> END")) {
                        // 发送完毕的标记，在结尾处打印
                    } else {
                        Log.e("okhttp_log________", "->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->");
                    }
                } else if (s.startsWith("<--")) {
                    if (s.startsWith("<-- END")) {

                    } else {
                        Log.e("okhttp_log________", "<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<");
                    }
                }

                Log.e("okhttp_log________", s);

                if (s.startsWith("--> END")) {
                    Log.e("okhttp_log________", "->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->->");
                } else if (s.startsWith("<-- END")) {
                    Log.e("okhttp_log________", "<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<");
                }
            }
        });
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        okHttpClientBuilder.addInterceptor(loggingInterceptor);

        return okHttpClientBuilder.build();
    }

    public void registerErrorHandler(ResponseHandler iErrorHandler) {
        iErrorHandlerList.add(iErrorHandler);
    }

    /**
     * 下划线连接转为小驼峰命名
     * 例如: json字符串的 auth_token 将为会赋值给 authToken 变量
     */
    private Gson createGson() {
        return new GsonBuilder()
                .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
                .create();
    }


}
